using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using Microsoft.EntityFrameworkCore;
using AutoMapper;
using AiPlatformAdmin.Api.Data;
using AiPlatformAdmin.Api.Models;
using AiPlatformAdmin.Api.DTOs;

namespace AiPlatformAdmin.Api.Controllers;

[Authorize(Roles = "SystemAdministrator")]
[ApiController]
[Route("api/token-usage")]
public class TokenUsageController : ControllerBase
{
    private readonly AppDbContext _context;
    private readonly IMapper _mapper;

    public TokenUsageController(AppDbContext context, IMapper mapper)
    {
        _context = context;
        _mapper = mapper;
    }

    [HttpGet]
    public async Task<ActionResult<IEnumerable<TokenUsageDto>>> GetTokenUsages(
        [FromQuery] int? userId = null,
        [FromQuery] int? agentId = null,
        [FromQuery] DateTime? startDate = null,
        [FromQuery] DateTime? endDate = null)
    {
        var query = _context.TokenUsages
            .Include(tu => tu.User)
            .Include(tu => tu.Agent)
            .AsQueryable();

        if (userId.HasValue)
        {
            query = query.Where(tu => tu.UserId == userId.Value);
        }

        if (agentId.HasValue)
        {
            query = query.Where(tu => tu.AgentId == agentId.Value);
        }

        if (startDate.HasValue)
        {
            query = query.Where(tu => tu.Timestamp >= startDate.Value);
        }

        if (endDate.HasValue)
        {
            query = query.Where(tu => tu.Timestamp <= endDate.Value);
        }

        var tokenUsages = await query.OrderByDescending(tu => tu.Timestamp).ToListAsync();

        return Ok(_mapper.Map<IEnumerable<TokenUsageDto>>(tokenUsages));
    }

    [HttpGet("{id}")]
    public async Task<ActionResult<TokenUsageDto>> GetTokenUsage(int id)
    {
        var tokenUsage = await _context.TokenUsages
            .Include(tu => tu.User)
            .Include(tu => tu.Agent)
            .FirstOrDefaultAsync(tu => tu.Id == id);

        if (tokenUsage == null)
        {
            return NotFound();
        }

        return Ok(_mapper.Map<TokenUsageDto>(tokenUsage));
    }

    [HttpPost]
    public async Task<ActionResult<TokenUsageDto>> CreateTokenUsage(CreateTokenUsageDto dto)
    {
        var tokenUsage = _mapper.Map<TokenUsage>(dto);
        tokenUsage.Timestamp = DateTime.UtcNow;

        _context.TokenUsages.Add(tokenUsage);
        await _context.SaveChangesAsync();

        // Reload with relationships
        await _context.Entry(tokenUsage).Reference(tu => tu.User).LoadAsync();
        await _context.Entry(tokenUsage).Reference(tu => tu.Agent).LoadAsync();

        return CreatedAtAction(nameof(GetTokenUsage), new { id = tokenUsage.Id }, _mapper.Map<TokenUsageDto>(tokenUsage));
    }

    [HttpGet("users/{userId}/summary")]
    public async Task<ActionResult<TokenUsageSummaryDto>> GetUserTokenSummary(int userId)
    {
        var user = await _context.Users.FindAsync(userId);
        if (user == null)
        {
            return NotFound();
        }

        var tokenUsages = await _context.TokenUsages
            .Where(tu => tu.UserId == userId)
            .ToListAsync();

        if (!tokenUsages.Any())
        {
            return Ok(new TokenUsageSummaryDto
            {
                TotalTokens = 0,
                TotalRequests = 0,
                FirstUsage = null,
                LastUsage = null
            });
        }

        return Ok(new TokenUsageSummaryDto
        {
            TotalTokens = tokenUsages.Sum(tu => tu.TokenCount),
            TotalRequests = tokenUsages.Count,
            FirstUsage = tokenUsages.Min(tu => tu.Timestamp),
            LastUsage = tokenUsages.Max(tu => tu.Timestamp)
        });
    }

    [HttpGet("agents/{agentId}/summary")]
    public async Task<ActionResult<TokenUsageSummaryDto>> GetAgentTokenSummary(int agentId)
    {
        var agent = await _context.Agents.FindAsync(agentId);
        if (agent == null)
        {
            return NotFound();
        }

        var tokenUsages = await _context.TokenUsages
            .Where(tu => tu.AgentId == agentId)
            .ToListAsync();

        if (!tokenUsages.Any())
        {
            return Ok(new TokenUsageSummaryDto
            {
                TotalTokens = 0,
                TotalRequests = 0,
                FirstUsage = null,
                LastUsage = null
            });
        }

        return Ok(new TokenUsageSummaryDto
        {
            TotalTokens = tokenUsages.Sum(tu => tu.TokenCount),
            TotalRequests = tokenUsages.Count,
            FirstUsage = tokenUsages.Min(tu => tu.Timestamp),
            LastUsage = tokenUsages.Max(tu => tu.Timestamp)
        });
    }

    [HttpDelete("{id}")]
    public async Task<IActionResult> DeleteTokenUsage(int id)
    {
        var tokenUsage = await _context.TokenUsages.FindAsync(id);
        if (tokenUsage == null)
        {
            return NotFound();
        }

        _context.TokenUsages.Remove(tokenUsage);
        await _context.SaveChangesAsync();

        return NoContent();
    }
}
